const { parse } = require('url')
const path = require('path')
const fs = require('fs')

const { WebSocketServer } = require('ws')
const { IdUtils } = require('../util/utils')
const { BaseSocket } = require('./webSocketUtil')
const { deCodeToken } = require('../util/jwt')
const wsServer = new WebSocketServer({
    noServer: true
})

const routerPath = path.join(path.dirname(__filename), 'router')
const routeMaps = new Map()
function readPaths(paths) {
    const routerFileList = fs.readdirSync(paths)
    for (let phs of routerFileList) {
        let files = path.join(paths, phs)
        let fileInfo = fs.statSync(files)
        if (fileInfo.isDirectory()) {
            readPaths(files)
        } else {
            let key = files.replace(routerPath, '').replace(/\\/g, '/').replace(/\.js/g, '')
            routeMaps.set(key, require(files))
        }
    }
}
function initRoute() {
    readPaths(routerPath)
    console.log('WebSocket路由', routeMaps);
}
/**
 * 初始化WebSocket路由
 */
initRoute()

/**
 * 心跳处理器
 */
const interval = setInterval(function ping() {
    wsServer.clients.forEach(function each(ws) {
        if (!ws.$baseSocket) return
        if (ws.$baseSocket.isAlive === false) return ws.$baseSocket.heartbeatClose()
        ws.$baseSocket.isAlive = false
        ws.$baseSocket.ping()
    });
}, 30000);

wsServer.on('close', () => {
    clearInterval(interval)
})

const UserAccess = function (baseSocket) {
    let token = baseSocket.request.headers['token'] || baseSocket.request.headers['sec-websocket-protocol']
    if (!token || token == '') {
        throw new Error("Token不存在")
    }
    const { id } = deCodeToken(token)
    baseSocket.uid = id
}
/**
 * WebSocket连接处理
 */
wsServer.on('connection', function connection(ws, request, client, route) {
    let baseSocket = new BaseSocket(ws, request, client, route)
    ws.$baseSocket = baseSocket
    try {
        let key = baseSocket.route.pathname.replace(/\/{2,}/, '/')
        if (routeMaps.has(key)) {
            let routeFun = routeMaps.get(key)
            baseSocket.routeFun = routeFun
        } else {
            baseSocket.outprintError("路由不存在")
            return
        }
    } catch (error) {
        console.error('WebSocket路由异常:' + error)
        baseSocket.outprintError("路由异常")
        return
    }
    try {
        /**
         * WebSocket授权
         */
        UserAccess(baseSocket)
    } catch (error) {
        baseSocket.outprintError(error.message)
        return
    }
    try {
        baseSocket.onOpen.bind(baseSocket)()
    } catch (error) {
        console.error('onOpen异常:' + error);
    }
    ws.on('pong', baseSocket.heartbeat.bind(baseSocket))
    ws.on('error', baseSocket.onError.bind(baseSocket))
    ws.on('message', baseSocket.onMessage.bind(baseSocket))
    ws.on('close', baseSocket.onClose.bind(baseSocket))
})
/**
 * 
 * @param {Request} request
 * @param {stream.Duplex} socket 
 * @param {Buffer} head 
 */
const startWebsocketServer = (request, socket, head) => {
    wsServer.handleUpgrade(request, socket, head, function done(ws) {
        let route = parse(request.url, true)
        // IdUtils.flakeId()
        wsServer.emit('connection', ws, request, null, route)
    });

}

module.exports = {
    startWebsocketServer
}